﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.UI;

// ReSharper disable once CheckNamespace
namespace com.nm.Helper
{
    /// <summary>
    /// Cookie操作类
    /// </summary>
    public static class CookiesHelper
    {
        #region SET VALUE

        #region HttpContext

        #region SET T

        public static void SetCookie<T>(this HttpContext context, string name, string key, T value) where T : struct
        {
            context.Response.SetCookie(name, key, value, null);
        }

        public static void SetCookie<T>(this HttpContext context, string name, string key, T value, DateTime expires) where T : struct
        {
            context.Response.SetCookie(name, key, value, expires);
        }

        public static void SetCookie<T>(this HttpContext context, string key, T value) where T : struct
        {
            context.Response.SetCookie(key, null, value, null);
        }

        public static void SetCookie<T>(this HttpContext context, string key, T value, DateTime expires) where T : struct
        {
            context.Response.SetCookie(key, null, value, expires);
        }

        #endregion SET T

        #region SET string

        public static void SetCookie(string name, string value, DateTime expires)
        {
            HttpContext.Current.SetCookie(name, value, expires);
        }

        public static void SetCookie(this HttpContext context, string name, string key, string value)
        {
            context.Response.SetCookie(name, key, value, null);
        }

        public static void SetCookie(this HttpContext context, string name, string key, string value, DateTime expires)
        {
            context.Response.SetCookie(name, key, value, expires);
        }

        public static void SetCookie(this HttpContext context, string key, string value)
        {
            context.Response.SetCookie(key, null, value, null);
        }

        public static void SetCookie(this HttpContext context, string key, string value, DateTime expires)
        {
            context.Response.SetCookie(key, null, value, expires);
        }

        #endregion SET string

        #endregion HttpContext

        #region System.Web.UI.MasterPage

        #region SET T

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie<T>(this System.Web.UI.MasterPage masterPage, string name, string key, T value) where T : struct
        {
            masterPage.Response.SetCookie(name, key, value, null);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie<T>(this System.Web.UI.MasterPage masterPage, string key, T value) where T : struct
        {
            masterPage.Response.SetCookie(key, null, value, null);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookie<T>(this System.Web.UI.MasterPage masterPage, string name, string key, T value, DateTime expires) where T : struct
        {
            masterPage.Response.SetCookie(name, key, value, expires);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookie<T>(this System.Web.UI.MasterPage masterPage, string key, T value, DateTime expires) where T : struct
        {
            masterPage.Response.SetCookie(key, null, value, expires);
        }

        #endregion SET T

        #region SET string

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie(this System.Web.UI.MasterPage masterPage, string name, string key, string value)
        {
            masterPage.Response.SetCookie(name, key, value, null);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie(this System.Web.UI.MasterPage masterPage, string key, string value)
        {
            masterPage.Response.SetCookie(key, null, value, null);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookie(this System.Web.UI.MasterPage masterPage, string name, string key, string value, DateTime expires)
        {
            masterPage.Response.SetCookie(name, key, value, expires);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="masterPage"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookie(this System.Web.UI.MasterPage masterPage, string key, string value, DateTime expires)
        {
            masterPage.Response.SetCookie(key, null, value, expires);
        }

        #endregion SET string

        #endregion System.Web.UI.MasterPage

        #region System.Web.UI.Page

        #region SET T

        public static void SetCookie<T>(this Page page, string name, string key, T value) where T : struct
        {
            page.Response.SetCookie(name, key, value, null);
        }

        public static void SetCookie<T>(this Page page, string name, string key, T value, DateTime expires) where T : struct
        {
            page.Response.SetCookie(name, key, value, expires);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie<T>(this Page page, string key, T value) where T : struct
        {
            page.Response.SetCookie(key, null, value, null);
        }

        public static void SetCookie<T>(this Page page, string key, T value, DateTime expires) where T : struct
        {
            page.Response.SetCookie(key, null, value, expires);
        }

        #endregion SET T

        #region SET string

        public static void SetCookie(this Page page, string name, string key, string value)
        {
            page.Response.SetCookie(name, key, value, null);
        }

        public static void SetCookie(this Page page, string name, string key, string value, DateTime expires)
        {
            page.Response.SetCookie(name, key, value, expires);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie(this Page page, string key, string value)
        {
            page.Response.SetCookie(key, null, value, null);
        }

        public static void SetCookie(this Page page, string key, string value, DateTime expires)
        {
            page.Response.SetCookie(key, null, value, expires);
        }

        #endregion SET string

        #endregion System.Web.UI.Page

        #region SET T

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="response"></param>
        /// <param name="key">关键字</param>
        /// <param name="value">值</param>
        public static void SetCookie<T>(this HttpResponse response, string key, T value) where T : struct
        {
            response.SetCookie(key, null, value, null);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="response"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookie<T>(this HttpResponse response, string key, T value, DateTime expires) where T : struct
        {
            response.SetCookie(key, null, value, expires);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="response"></param>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void SetCookie<T>(this HttpResponse response, string name, string key, T value) where T : struct
        {
            response.SetCookie(name, key, value.ToString(), null);
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <typeparam name="T">结构（struct）类型的值 比如 int</typeparam>
        /// <param name="response"></param>
        /// <param name="name"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookie<T>(this HttpResponse response, string name, string key, T value, DateTime? expires)
            where T : struct
        {
            response.SetCookie(name, key, value.ToString(), expires);
        }

        #endregion SET T

        #region SET string

        public static void SetCookie(this HttpResponse response, string key, string value)
        {
            response.SetCookie(key, null, value, null);
        }

        public static void SetCookie(this HttpResponse response, string key, string value, DateTime? expires)
        {
            response.SetCookie(key, null, value, expires);
        }

        public static void SetCookie(this HttpResponse response, string name, string key, string value)
        {
            response.SetCookie(name, key, value, null);
        }

        public static void SetCookie(this HttpResponse response, string name, string key, string value, DateTime? expires)
        {
            var cookie = response.Cookies[name];
            if (cookie == null) return;
            if (!string.IsNullOrEmpty(key) && cookie.HasKeys)
                cookie.Values.Set(key, value);
            else
                if (!string.IsNullOrEmpty(value))
                cookie.Value = value;
            if (expires != null)
                cookie.Expires = expires.Value;
            response.SetCookie(cookie);
        }

        #endregion SET string

        #endregion SET VALUE

        #region GET VALUE

        #region GET string

        public static string GetCookie(this HttpContext context, string name, string key, string dv)
        {
            return context.Request.GetCookie(name, key, dv);
        }

        public static string GetCookie(this HttpContext context, string key, string dv)
        {
            return context.Request.GetCookie(key, null, dv);
        }

        public static string GetCookie(this HttpContext context, string key)
        {
            return context.Request.GetCookie(key, null, string.Empty);
        }

        public static string GetCookie(this Page page, string name, string key, string dv)
        {
            return page.Request.GetCookie(name, key, dv);
        }

        public static string GetCookie(this Page page, string key, string dv)
        {
            return page.Request.GetCookie(key, null, dv);
        }

        public static string GetCookie(this Page page, string key)
        {
            return page.Request.GetCookie(key, null, string.Empty);
        }

        public static string GetCookie(this HttpRequest request, string name, string key, string dv)
        {
            if (!request.Cookies.AllKeys.Contains(name)) return dv;
            var cookie = request.Cookies[name];
            return Get(cookie, key, dv);
        }

        public static string GetCookieValue(string name)
        {
            return HttpContext.Current.Request.GetCookie(name);
        }

        public static int GetCookieValue(string name, int dv)
        {
            var r = HttpContext.Current.Request.GetCookie(name);
            if (string.IsNullOrWhiteSpace(r)) return dv;
            var ri = 0;
            return int.TryParse(r, out ri) ? ri : dv;
        }

        public static string GetCookie(this HttpRequest request, string key, string dv)
        {
            return request.GetCookie(key, null, dv);
        }

        public static string GetCookie(this HttpRequest request, string key)
        {
            return request.GetCookie(key, null, string.Empty);
        }

        #endregion GET string

        #region Get T

        public static T GetCookie<T>(this HttpRequest request, string name, string key, T dv) where T : struct
        {
            if (!request.Cookies.AllKeys.Contains(name)) return dv;
            var cookie = request.Cookies[name];
            return Get(cookie, key, dv);
        }

        public static T GetCookie<T>(this HttpRequest request, string key, T dv) where T : struct
        {
            return request.GetCookie(key, null, dv);
        }

        public static T GetCookie<T>(this Page page, string name, string key, T dv) where T : struct
        {
            return page.Request.GetCookie(name, key, dv);
        }

        public static T GetCookie<T>(this Page page, string key, T dv) where T : struct
        {
            return page.Request.GetCookie(key, null, dv);
        }

        private static T Get<T>(HttpCookie cookie, string key, T dv) where T : struct
        {
            var r = Get(cookie, key, string.Empty);
            var converter = TypeDescriptor.GetConverter(dv.GetType());
            if (!converter.CanConvertFrom(typeof(string))) return dv;
            if (string.IsNullOrWhiteSpace(r)) return dv;
            var rr = converter.ConvertFrom(r);
            return rr == null ? dv : (T)rr;
        }

        #endregion Get T

        private static string Get(HttpCookie cookie, string key, string dv)
        {
            if (!cookie.HasKeys)
                return string.IsNullOrWhiteSpace(cookie.Value) ? dv : cookie.Value;
            if (string.IsNullOrWhiteSpace(key))
            {
                return dv;
            }
            var r = cookie.Values[key];
            if (string.IsNullOrWhiteSpace(r)) return dv;
            return string.IsNullOrWhiteSpace(cookie.Value) ? dv : cookie.Value;
        }

        #endregion GET VALUE

        #region Remove

        public static void RemoveCookie(this Page page, string name)
        {
            page.Response.RemoveCookie(name);
        }

        public static void RemoveCookie(this Page page, string name, string key)
        {
            page.Response.RemoveCookie(name, key);
        }

        public static void RemoveCookie(this HttpResponse response, string name)
        {
            response.RemoveCookie(name, null);
        }

        public static void RemoveCookie(this HttpResponse response, string name, string key)
        {
            var cookie = response.Cookies[name];
            if (cookie == null) return;
            if (!string.IsNullOrEmpty(key) && cookie.HasKeys)
                cookie.Values.Remove(key);
            else
                response.Cookies.Remove(name);
        }

        #endregion Remove
    }
}